home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / CH_5.2 / structrid / structrid.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-11  |  7.5 KB  |  239 lines

  1. /*
  2.  * structrid.c
  3.  *
  4.  * Practical Algorithms for Image Analysis
  5.  *
  6.  * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
  7.  */
  8.  
  9. /* STRUCTRID:   program takes input PCC, removes structures whose total
  10.  *            length of lines or bounding box area is below or above
  11.  *              the chosen thresholds, and writes output PCC 
  12.  *              usage: structrid infile outfile [-ll] [-hl] [-la] [-ha] [-L]
  13.  *
  14.  */
  15.  
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include "pcc2.h"               /* header file for PCC programs */
  20. extern void print_sos_lic ();
  21.  
  22. unsigned char *fcCode;          /* code storage */
  23. long nByteCode;                 /* no. bytes in code storage */
  24.  
  25. int tlc3rid (struct attributes *, long, struct structures *, long *,
  26.              long, long, long, long);
  27. int usage (short);
  28. int input (int, char **, long *, long *, long *, long *);
  29.  
  30. main (argc, argv)
  31.      int argc;
  32.      char *argv[];
  33.  
  34. {
  35.   long width, height;           /* image size */
  36.   long lowLength, highLength,   /* range of lengths to retain */
  37.     lowArea, highArea;          /* range of areas to retain */
  38.   struct attributes *attr;      /* level 1 attributes */
  39.   long nAttr;                   /* no. of line structures in attr. array */
  40.   struct structures *structs;   /* level 3 line structures */
  41.   long nStructs;                /* no. of connected structures in image */
  42.  
  43.   if ((input (argc, argv, &lowLength, &highLength, &lowArea, &highArea))
  44.       < 0)
  45.     return (-1);
  46.  
  47.   lowLength *= 10;              /* lengths are scaled */
  48.   highLength *= 10;
  49.  
  50. /* open input PCC file */
  51.   if (pccread (argv[1], &fcCode, &nByteCode, &width, &height) == -1)
  52.     exit (1);
  53.   printf ("image size: %dx%d, PCC length = %d\n",
  54.           width, height, nByteCode);
  55.  
  56. /* construct tables of PCC decodes */
  57.   pccdecodes ();
  58.  
  59. /* construct TLC level 1 array of attributes */
  60.   tlc1attr (&attr, &nAttr);
  61.   printf ("%d level 1 line features\n", nAttr);
  62.  
  63. /* find level 3 connected structures */
  64.   tlc3structs (attr, nAttr, &structs, &nStructs);
  65.   printf ("%d level 3 structures\n", nStructs);
  66.  
  67. /* determine level 3 features */
  68.   tlc3feats (attr, nAttr, structs, nStructs);
  69.   tlc3rid (attr, nAttr, structs, &nStructs,
  70.            lowLength, highLength, lowArea, highArea);
  71.   printf ("%d level 3 structures remaining, %d code bytes.\n",
  72.           nStructs, nByteCode);
  73.  
  74. /* write out PCC file */
  75.   if (nStructs > 0)
  76.     pccwrite (argv[2], fcCode, nByteCode, width, height);
  77.   else
  78.     printf ("No output file -- all structures filtered out.\n");
  79.  
  80.   return (0);
  81. }
  82.  
  83.  
  84.  
  85. /* TLC3RID:   function removes any level 3 structures above or below threshold
  86.  *              usage: tlc3rid (attr, nAttr, structs, &nStructs,
  87.  *                                  lowLength, highLength, lowArea, highArea)
  88.  */
  89.  
  90. int
  91. tlc3rid (attr, nAttr, structs, nStructs, lowLength, highLength,
  92.          lowArea, highArea)
  93.      struct attributes *attr;   /* level 1 attributes */
  94.      long nAttr;                /* no. level 1 attributes */
  95.      struct structures *structs;  /* level 3 attributes */
  96.      long *nStructs;            /* no. level 3 attributes */
  97.      long lowLength, highLength,  /* length range to retain (*10) */
  98.        lowArea, highArea;       /* area range to retain */
  99. {
  100.   long strtCode, endCode,       /* bounds of code for structure */
  101.     iStopByte,                  /* position of STOPBYTE */
  102.     nStructsOut,                /* no. of structures after removal */
  103.     iStructs,                   /* level 3 increment */
  104.     iCode,                      /* input PCC incrementor */
  105.     iOut;                       /* output PCC incrementor */
  106.   struct structures strct;      /* level 3 structure */
  107.   long lx, ly,                  /* lengths of bounding box */
  108.     area;                       /* area of bounding box */
  109.  
  110. /* find position of STOPCODE (I'm inconsistent I think in putting 4 bytes
  111.  * trailing this or not, so we'll find it) */
  112.   for (iStopByte = nByteCode - 1; iStopByte > 0; --iStopByte)
  113.     if (fcCode[iStopByte] == STOPCODE)
  114.       break;
  115.  
  116. /* read code, and write code which is not deleted */
  117.   nStructsOut = 0;
  118.   for (iStructs = 0, iOut = 0; iStructs < *nStructs; iStructs++) {
  119.     strct = structs[iStructs];
  120.     strtCode = attr[strct.iAttr].iByteCode - 5;
  121.     endCode = (iStructs + 1 < *nStructs) ?
  122.       attr[structs[iStructs + 1].iAttr].iByteCode - 6 : iStopByte - 1;
  123.     lx = (strct.box.max.x - strct.box.min.x);
  124.     ly = (strct.box.max.y - strct.box.min.y);
  125.     if (lx == 0)
  126.       lx = 1;
  127.     if (ly == 0)
  128.       ly = 1;
  129.     area = lx * ly;
  130.     if (area < 0)
  131.       area *= -1;
  132.     if (strct.length >= lowLength && strct.length < highLength
  133.         && area >= lowArea && area < highArea) {
  134.       nStructsOut++;
  135.       for (iCode = strtCode; iCode <= endCode; iCode++)
  136.         fcCode[iOut++] = fcCode[iCode];
  137.     }
  138.   }
  139.  
  140.   for (iCode = iStopByte; iCode < nByteCode; iCode++)
  141.     fcCode[iOut++] = fcCode[iCode];
  142.   *nStructs = nStructsOut;
  143.   nByteCode = iOut;
  144.   return (0);
  145. }
  146.  
  147.  
  148.  
  149. /* USAGE:       function gives instructions on usage of program
  150.  *                    usage: usage (flag)
  151.  *              When flag is 1, the long message is given, 0 gives short.
  152.  */
  153.  
  154. int
  155. usage (flag)
  156.      short flag;                /* flag =1 for long message; =0 for short message */
  157. {
  158.  
  159. /* print short usage message or long */
  160.   printf ("USAGE: structrid infile outfile [-ll] [-hl] [-la] [-ha] [-L]\n");
  161.   if (flag == 0)
  162.     return (-1);
  163.  
  164.   printf ("\nstructrid filters line structures, that is, objects\n");
  165.   printf ("made up of one or many connected line segments, removing\n");
  166.   printf ("those whose features are outside of the range given.\n\n");
  167.   printf ("ARGUMENTS:\n");
  168.   printf ("    infile: input filename (PCC) \n");
  169.   printf ("   outfile: output filename (PCC) \n\n");
  170.   printf ("OPTIONS:\n");
  171.   printf ("    -ll LOW LENGTH: lowest length structure to retain.\n");
  172.   printf ("   -hl HIGH LENGTH: highest length structure to retain.\n");
  173.   printf ("      -la LOW AREA: lowest bounding box of structure to retain.\n");
  174.   printf ("     -ha HIGH AREA: highest bounding box of structure to retain.\n");
  175.   printf ("                -L: print Software License for this module\n");
  176.  
  177.   return (-1);
  178. }
  179.  
  180.  
  181. /* INPUT:       function reads input parameters
  182.  *                    usage: input (argc, argv, &lowLength, &highLength,
  183.  *                                      &lowArea, &highArea)
  184.  */
  185.  
  186. #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
  187.  
  188. int
  189. input (argc, argv, lowLength, highLength, lowArea, highArea)
  190.      int argc;
  191.      char *argv[];
  192.      long *lowLength, *highLength;  /* lowest and highest lengths to retain */
  193.      long *lowArea, *highArea;  /* lowest and highest areas to retain */
  194. {
  195.   long n;
  196.  
  197.   static char *llString = "-ll";
  198.   static char *hlString = "-hl";
  199.   static char *laString = "-la";
  200.   static char *haString = "-ha";
  201.  
  202.   if (argc < 3)
  203.     USAGE_EXIT (1);
  204.  
  205.   *lowLength = *lowArea = 0;
  206.   *highLength = *highArea = 100000000;
  207.  
  208.   for (n = 3; n < argc; n++) {
  209.     if (strcmp (argv[n], "-ll") == 0) {
  210.       if (++n == argc || argv[n][0] == '-')
  211.         USAGE_EXIT (0);
  212.       *lowLength = atol (argv[n]);
  213.     }
  214.     else if (strcmp (argv[n], "-hl") == 0) {
  215.       if (++n == argc || argv[n][0] == '-')
  216.         USAGE_EXIT (0);
  217.       *highLength = atol (argv[n]);
  218.     }
  219.     else if (strcmp (argv[n], "-la") == 0) {
  220.       if (++n == argc || argv[n][0] == '-')
  221.         USAGE_EXIT (0);
  222.       *lowArea = atol (argv[n]);
  223.     }
  224.     else if (strcmp (argv[n], "-ha") == 0) {
  225.       if (++n == argc || argv[n][0] == '-')
  226.         USAGE_EXIT (0);
  227.       *highArea = atol (argv[n]);
  228.     }
  229.     else if (strcmp (argv[n], "-L") == 0) {
  230.       print_sos_lic ();
  231.       exit (0);
  232.     }
  233.     else
  234.       USAGE_EXIT (0);
  235.   }
  236.  
  237.   return (0);
  238. }
  239.